home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Sample.bin / CollateDemo.java < prev    next >
Text File  |  1998-09-15  |  33KB  |  1,001 lines

  1. /*
  2.  * @(#)CollateDemo.java     1.1 98/06/16
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
  8.  *
  9.  *   The original version of this source code and documentation is copyrighted
  10.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  11.  * materials are provided under terms of a License Agreement between Taligent
  12.  * and Sun. This technology is protected by multiple US and International
  13.  * patents. This notice and attribution to Taligent may not be removed.
  14.  *   Taligent is a registered trademark of Taligent, Inc.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software
  17.  * and its documentation for NON-COMMERCIAL purposes and without
  18.  * fee is hereby granted provided that this copyright notice
  19.  * appears in all copies. Please refer to the file "copyright.html"
  20.  * for further important copyright and licensing information.
  21.  *
  22.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  23.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  25.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  26.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  27.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  28.  *
  29.  */
  30.  
  31. import java.applet.Applet;
  32. import java.awt.event.*;
  33. import java.awt.*;
  34. import java.util.Locale;
  35. import java.util.Vector;
  36. import java.text.NumberFormat;
  37. import java.text.Collator;
  38. import java.text.RuleBasedCollator;
  39. import java.text.ParseException;
  40.  
  41. /**
  42.  * Concrete class for demonstrating language sensitive collation.
  43.  * The following is the instruction on how to run the collation demo.
  44.  * <p>
  45.  * ===================
  46.  * <H3>Customization</H3>
  47.  * You can produce a new collation by adding to or changing an existing
  48.  * one.
  49.  * <H4>To show...</H4>
  50.  * <BLOCKQUOTE>You can modify an existing collation to show how this works.
  51.  * By adding items at the end of a collation you override earlier
  52.  * information.
  53.  * Watch how you can make the letter P sort at the end of the
  54.  * alphabet.</BLOCKQUOTE>
  55.  * <H4>Do...</H4>
  56.  * <BLOCKQUOTE>1. Scroll to the end of the Sequence field. After the Z,
  57.  * type
  58.  * "< p , P". This will put the letter P (with both of its
  59.  * case
  60.  * variants) at the end of the alphabet. Hit the Set Rule button. This creates
  61.  * a new collation with the name "Custom-1" (you could give it a
  62.  * different name by typing in the Collator Name field). When you now look
  63.  * at the Text field, you will see that you have changed the sequence to put
  64.  * <I>Pat</I>
  65.  * at the end. (If you did not have Sort Ascending on, click it
  66.  * now.)</BLOCKQUOTE>
  67.  * <BR>
  68.  * Making P sort at the end may not seem terribly useful, but it is used to
  69.  * make modifications in the sorting sequence for different languages.
  70.  * <H4>To show...</H4>
  71.  * <BLOCKQUOTE>For example, you can add CH as a single letter after C, as
  72.  * in
  73.  * traditional Spanish sorting.</BLOCKQUOTE>
  74.  * <H4>Do...</H4>
  75.  * <BLOCKQUOTE>Enter in the following after Z; "& C < ch , cH, Ch,
  76.  * CH".
  77.  * Hit the Set Rule button, type in test words in the Text field (such as
  78.  * "czar",
  79.  * "churo" and "darn"), and select Sort Ascending to
  80.  * see
  81.  * the resulting sort order.</BLOCKQUOTE>
  82.  * <H4>To show...</H4>
  83.  * <BLOCKQUOTE>You can also add other sequences to the collation rules,
  84.  * such as sorting symbols with their alphabetic equivalents.</BLOCKQUOTE>
  85.  * <H4>Do...</H4>
  86.  * <BLOCKQUOTE>1. Scroll to the end of the Sequence field. After the end,
  87.  * type the following list (you can just select this text in your browser and
  88.  * paste it in, to avoid typing). Now type lines in the Text field with these
  89.  * symbols on them, and select Sort Ascending to see the resulting sort
  90.  * order.</BLOCKQUOTE>
  91.  * <UL>
  92.  *   <UL>
  93.  *     <LI>& Asterisk ; *
  94.  *     <LI>& Question-mark ; ?
  95.  *     <LI>& Hash-mark ; #
  96.  *     <LI>& Exclamation-mark ; !
  97.  *     <LI>& Dollar-sign ; $
  98.  *     <LI>& Ampersand ; '&';
  99.  *   </UL>
  100.  * </UL>
  101.  * <H4>Details</H4>
  102.  * If you are an advanced user and interested in trying out more rules,
  103.  * here is a brief explanation of how they work. The sequence is a list of
  104.  * rules. Each rule is of two forms:
  105.  * <UL>
  106.  *   <LI><modifier>
  107.  *   <LI><relation> <text-argument>
  108.  *   <LI><reset> <text-argument>
  109.  * </UL>
  110.  * <H5>Modifier</H5>
  111.  * <BLOCKQUOTE>@ Indicates that accents are sorted backwards, as in
  112.  * French</BLOCKQUOTE>
  113.  * <H5>Text-argument</H5>
  114.  * The text can be any number of characters (if you want to include special
  115.  * characters, such as space, use single-quotes around them).
  116.  * <H5>Relation</H5>
  117.  * The relations are the following:
  118.  * <DL>
  119.  *   <DD><    Greater, as a letter difference (primary)
  120.  *   <DD>;    Greater, as an accent difference (secondary)
  121.  *   <DD>,    Greater, as a case difference (tertiary)
  122.  *   <DD>=    Equal
  123.  *   <DD>&    Reset previous comparison.
  124.  * </DL>
  125.  * <H5>Reset</H5>
  126.  * The "&" is special in that does not put the text-argument
  127.  * into the sorting sequence; instead, it indicates that the <I>next</I>
  128.  * rule is with respect to where the text-argument <I>would be</I> sorted.
  129.  * This sounds more complicated than it is in practice. For example, the
  130.  * following are equivalent ways of expressing the same thing:
  131.  * <UL>
  132.  *   <LI>a < b < c
  133.  *   <LI>a < b & b < c
  134.  *   <LI>a < c & a < b
  135.  * </UL>
  136.  * Notice that the order is important, since the subsequent item goes
  137.  * <I>immediately</I>
  138.  * after the text-argument. The following are <I>not</I> equivalent:
  139.  * <UL>
  140.  *   <LI>a < b & a < c
  141.  *   <LI>a < c & a < b
  142.  * </UL>
  143.  * The text-argument must already be present in the sequence, or some
  144.  * initial substring of the text-argument must be present. (e.g. "a <
  145.  * b& ae < e" is valid since "a" is present in the
  146.  * sequence<I>before</I> "ae" is reset). In this latter case,
  147.  * "ae"
  148.  * is <B><I>not</I></B> entered and treated as a single character; instead,
  149.  * "e" is sorted as if it were expanded to two characters:
  150.  * "a"
  151.  * followed by an "e".<BR>
  152.  * This difference appears in natural languages: in traditional Spanish
  153.  * "ch"
  154.  * is treated as though it <I>contracts</I> to a single character
  155.  * (expressed
  156.  * as "c < ch < d"), while in traditional German
  157.  * "ä"
  158.  * (a-umlaut) is treated as though it <I>expands</I> to two characters
  159.  * (expressed
  160.  * as "a & ae ; ä < b").<BR>
  161.  * <H5>Ignorable Characters</H5>
  162.  * The first rule must start with a relation (the examples we have used are
  163.  * fragments; "a < b" really should be "< a <
  164.  * b").
  165.  * If, however, the first relation is not "<", then all the
  166.  * all
  167.  * text-arguments up to the first "<" are ignorable. For
  168.  * example,
  169.  * ", - < a < b" makes "-" an ignorable
  170.  * character,
  171.  * as we saw earlier in the word "black-birds".<BR>
  172.  * <H5>Accents</H5>
  173.  * The Collator automatically normalizes text internally to separate
  174.  * accents
  175.  * from base characters where possible. So, if you type in an
  176.  * "ä"
  177.  * (a-umlaut), after you reset the collation you will see
  178.  * "a\u0308"
  179.  * in the sequence, where \u0308 is the Java syntax for umlaut. The
  180.  * demonstration
  181.  * program uses this syntax instead of just showing the umlaut since many
  182.  * browsers are unable to display the umlaut yet.<BR>
  183.  * <H4>Errors</H4>
  184.  * The following are errors:
  185.  * <UL>
  186.  *   <LI>Two relations in a row (e.g. "a < , b"
  187.  *   <LI>Two text arguments in a row (e.g. "a < b c < d")
  188.  *   <LI>A reset where the text-argument is not already in the sequence
  189.  * (e.g."a < b & e < f")
  190.  * </UL>
  191.  * If you produce one of these errors, then the demonstration will beep at
  192.  * you, and select the offending text (note: on some browsers, the
  193.  * selection will not appear correctly).
  194.  * @version    1.1 11/23/96
  195.  * @author     Kathleen Wilson, Helena Shih
  196.  * @see        java.util.Collator
  197.  * @see        java.util.RuleBasedCollator
  198.  * @see        java.demos.utilities.DemoApplet
  199.  */
  200. public class CollateDemo extends DemoApplet
  201. {
  202.     /**
  203.      * The main function which defines the behavior of the CollateDemo applet
  204.      * when an applet is started.
  205.      */
  206.     public static void main(String argv[]) {
  207.         DemoApplet.showDemo(new CollateFrame(null));
  208.     }
  209.  
  210.     /**
  211.      * This creates a CollateFrame for the demo applet.
  212.      */
  213.     public Frame createDemoFrame(DemoApplet applet) {
  214.         return new CollateFrame(applet);
  215.     }
  216. }
  217.  
  218. /**
  219.  * A Frame is a top-level window with a title. The default layout for a frame
  220.  * is BorderLayout.  The CollateFrame class defines the window layout of
  221.  * CollateDemo.
  222.  */
  223. class CollateFrame extends Frame implements WindowListener, ActionListener, ItemListener, KeyListener
  224. {
  225.  
  226.     /**
  227.      * Constructs a new CollateFrame that is initially invisible.
  228.      */
  229.     public CollateFrame(DemoApplet applet)
  230.     {
  231.         super("Collate Demo");
  232.         this.applet = applet;
  233.     addWindowListener(this);
  234.         init();
  235.         start();
  236.     }
  237.  
  238.     /**
  239.      * Called if an action occurs in the CollateFrame object.
  240.      */
  241.     public boolean action(Event evt, Object obj)
  242.     {
  243.         return false;
  244.     }
  245.  
  246.     /**
  247.      * Initializes the applet. You never need to call this directly, it
  248.      * is called automatically by the system once the applet is created.
  249.      */
  250.     public void init()
  251.     {
  252.         theLocale = Locale.US;
  253.         theCollation = Collator.getInstance(theLocale);
  254.         buildGUI();
  255.     }
  256.  
  257.     /**
  258.      * Called to start the applet. You never need to call this method
  259.      * directly, it is called when the applet's document is visited.
  260.      */
  261.     public void start()
  262.     {
  263.     }
  264.  
  265.   public void itemStateChanged(ItemEvent e) {
  266.     errorText("");
  267.     if (e.getSource() == sortAscending)
  268.       handleSort(true, false);
  269.     else if (e.getSource() == sortDescending)
  270.       handleSort(false, true);
  271.     else if (e.getSource() == localeChoice) {
  272.       handleLocale();
  273.       handleSort(sortAscending.getState(), sortDescending.getState());
  274.     }
  275.     else if (e.getSource() == decompChoice) {
  276.       handleSort(sortAscending.getState(), sortDescending.getState());
  277.     }
  278.     else if (e.getSource() == strengthChoice) {
  279.       handleSort(sortAscending.getState(), sortDescending.getState());
  280.     }
  281.   }
  282.  
  283.   public void keyPressed(KeyEvent e) {
  284.     if (e.getSource() == textentry) {
  285.       checkboxes.setSelectedCheckbox(noSort);
  286.     }
  287.   }
  288.  
  289.   public void keyReleased(KeyEvent e) {
  290.   }
  291.  
  292.   public void keyTyped(KeyEvent e) {
  293.   }
  294.  
  295.   public void actionPerformed(ActionEvent e) {
  296.     if (e.getSource() == collateRulesButton) {
  297.       errorText("");
  298.       collateRulesButton.setLabel("setting");
  299.       handleSetRules();
  300.       collateRulesButton.setLabel("Set Rules");
  301.       handleSort(sortAscending.getState(),
  302.                  sortDescending.getState());
  303.     }
  304.     
  305.   }
  306.  
  307.   public void windowClosed(WindowEvent e) {
  308.   }
  309.  
  310.   public void windowDeiconified(WindowEvent e) {
  311.   }
  312.  
  313.   public void windowIconified(WindowEvent e) {
  314.   }
  315.  
  316.   public void windowActivated(WindowEvent e) {
  317.   }
  318.  
  319.   public void windowDeactivated(WindowEvent e) {
  320.   }
  321.  
  322.   public void windowOpened(WindowEvent e) {
  323.   }
  324.  
  325.   public void windowClosing(WindowEvent e) {
  326.     setVisible(false);
  327.     dispose();
  328.  
  329.     if (applet != null) {
  330.       applet.demoClosed();
  331.     } else System.exit(0);
  332.  
  333.   }
  334.   
  335.  
  336.     /**
  337.      * This function is called when you press the "SortDescend" button.
  338.      * It does an extremely simple sort, using the Collator.compare function.
  339.      * To improve performance, you could transform the strings into
  340.      * a sort key which is a series of characters that can be
  341.      * compared using bit-wise comparison.  In addition, you can also use
  342.      * collation keys to compare two strings based on the collation rules.
  343.      * @see java.util.Collator#compare
  344.      * @see java.util.Collator#getSortKey
  345.      * @see java.util.Collator#getCollationKey
  346.      */
  347.  
  348.     public boolean handleSort(boolean ascending, boolean descending) {
  349.         if (ascending == descending)
  350.             return true;
  351.         int exchangeResult = ascending ? -1 : 1;
  352.  
  353.         InitializeListVector();
  354.  
  355.         String targetItem;
  356.         String sourceItem;
  357.         byte compareResult;
  358.  
  359.  
  360.         String strengthName = strengthChoice.getSelectedItem();
  361.         if (strengthName.equals(tertiary)) {
  362.              theCollation.setStrength(Collator.TERTIARY);
  363.         }else if (strengthName.equals(secondary)) {
  364.              theCollation.setStrength(Collator.SECONDARY);
  365.         } else theCollation.setStrength(Collator.PRIMARY);
  366.  
  367.         int decompItem = decompChoice.getSelectedIndex();
  368.         if (decompItem == 0) {
  369.              theCollation.setDecomposition(Collator.NO_DECOMPOSITION);
  370.         }else if (decompItem == 1) {
  371.              theCollation.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
  372.         } else theCollation.setDecomposition(Collator.FULL_DECOMPOSITION);
  373.  
  374.         int numItems = textList.size();
  375.         for (int sourceIndex = 1; sourceIndex < numItems; sourceIndex++)
  376.         {
  377.            sourceItem = (String) textList.elementAt(sourceIndex);
  378.            for (int targetIndex = 0; targetIndex < sourceIndex; targetIndex++)
  379.            {
  380.                  targetItem = (String) textList.elementAt(targetIndex);
  381.               compareResult = (byte) theCollation.compare(sourceItem, targetItem);
  382.               if (compareResult == exchangeResult)
  383.               {
  384.                 textList.removeElementAt(sourceIndex);
  385.                 textList.insertElementAt(sourceItem, targetIndex);
  386.                 break;
  387.               }
  388.            }
  389.         }
  390.         resetTextArea();
  391.         return true;
  392.     }
  393.  
  394.     /**
  395.      * This function is called when you press the Locale button.
  396.      * It sets the locale that is to be used to create the collation object.
  397.      * @see java.util.Collator#getInstance
  398.      */
  399.     public boolean handleLocale()
  400.     {
  401.         int index = localeChoice.getSelectedIndex();
  402.  
  403.         theCollation = collations[index];
  404.         String theRules = ruleStrings[index];
  405.  
  406.         if (theRules != null)
  407.         {
  408.              ruleEntry.setText(createUnicodeString
  409.                  (((RuleBasedCollator)theCollation).getRules()));
  410.         } else ruleEntry.setText("");
  411.  
  412.         return true;
  413.     }
  414.  
  415.     /**
  416.      * This function is called when you press the "Set Rules" button.
  417.      * It sets the rules that are to be used by the current collation object.
  418.      * @see java.util.RuleBasedCollator#getRules
  419.      */
  420.     public void handleSetRules()
  421.     {
  422.         int index = localeChoice.getSelectedIndex();
  423.  
  424.         String rules = ruleEntry.getText();
  425.         if ((rules.equals(ruleStrings[index]) == false)
  426.              && (theCollation instanceof RuleBasedCollator) )
  427.         {
  428.             int idx = 0;
  429.             try
  430.             {
  431.                 String collName = collationName.getText();
  432.                 for (int n = 0; n < localeChoice.getItemCount(); n++)
  433.                 {
  434.                     if (collName.equals(localeChoice.getItem(n)))
  435.                     {
  436.                         theCollation = new
  437.                             RuleBasedCollator(convertStringToRules(rules));
  438.                         collations[n] = theCollation;
  439.                         idx = n;
  440.                         break;
  441.                     }
  442.                 }
  443.                 if (idx == 0)
  444.                 {
  445.                     if (collName.startsWith("custom-"))
  446.                     {
  447.                         untitledIndex++;
  448.                     }
  449.                     if (localeChoice.getItemCount() < MAX_COLLATIONS)
  450.                     {
  451.                         idx = localeChoice.getItemCount();
  452.                         theCollation = new
  453.                             RuleBasedCollator(convertStringToRules(rules));
  454.                         collations[idx] = theCollation;
  455.                         localeChoice.addItem( collName );
  456.                     }
  457.                     else
  458.                     {
  459.                         throw new ParseException("Max # exceeded!" +
  460.                             "Please replace an existing one.", 0);
  461.                     }
  462.                 }
  463.                 localeChoice.select(idx);
  464.                 ruleStrings[idx] = rules;
  465.                 ruleEntry.setText(createUnicodeString
  466.                     (((RuleBasedCollator)theCollation).getRules()));
  467.                 if (localeChoice.getItemCount() < MAX_COLLATIONS)
  468.                     collationName.setText("custom-" + untitledIndex);
  469.             }
  470.             catch (ParseException foo)
  471.             {
  472.                 collateRulesButton.setLabel("Set Rules");
  473.                 errorText(foo.getMessage());
  474.             }
  475.         }
  476.     }
  477.     /**
  478.      * Must be called after the array of locales has been initialized.
  479.      */
  480.  
  481.     public void loadCollationTables()
  482.     {
  483.         MAX_COLLATIONS = locales.length + 10;
  484.         collations = new Collator[MAX_COLLATIONS];
  485.         ruleStrings = new String[MAX_COLLATIONS];
  486.         for (int i = 0; i < locales.length; i++)
  487.         {
  488.            Locale currentLocale = locales[i];
  489.            Collator newcollation = null;
  490.  
  491.            //If the collation for this language has already
  492.            //been created, then use it.
  493.            int j = 0;
  494.            for (; j < i; j++)
  495.            {
  496.                 if (currentLocale.getLanguage() == locales[j].getLanguage())
  497.                 {
  498.                     newcollation = collations[j];
  499.                 break;
  500.                 }
  501.            }
  502.  
  503.             if (newcollation == null)
  504.             {
  505.                 collations[i] = Collator.getInstance(currentLocale);
  506.                 if (collations[i] instanceof RuleBasedCollator)
  507.                 {
  508.                     String ruleText = ((RuleBasedCollator)
  509.                         collations[i]).getRules();
  510.                     ruleStrings[i] = createUnicodeString(ruleText);
  511.                 }
  512.             }else {
  513.                 collations[i] = newcollation;
  514.                 ruleStrings[i] = ruleStrings[j];
  515.             }
  516.         }
  517.     }
  518.  
  519.     //------------------------------------------------------------
  520.     // package private
  521.     //------------------------------------------------------------
  522.  
  523.     Panel makePanel(Component demo, Component code) {
  524.         Panel temp = new Panel();
  525.  
  526.         GridBagLayout gridbag = new GridBagLayout();
  527.         GridBagConstraints constraints = new GridBagConstraints();
  528.         temp.setLayout(gridbag);
  529.  
  530.         constraints.anchor = GridBagConstraints.NORTHWEST;
  531.            constraints.gridwidth = GridBagConstraints.REMAINDER; //end row
  532.         gridbag.setConstraints(demo, constraints);
  533.  
  534.            constraints.gridheight = GridBagConstraints.REMAINDER; //end column
  535.         gridbag.setConstraints(code, constraints);
  536.  
  537.         temp.add(demo);
  538.         temp.add(code);
  539.         return temp;
  540.     }
  541.  
  542.     void addWithFont(Container container, Component foo, Font font) {
  543.         if (font != null)
  544.             foo.setFont(font);
  545.         container.add(foo);
  546.     }
  547.  
  548.     void buildGUI()
  549.     {
  550.         setBackground(Color.white);
  551.         setLayout(new BorderLayout());
  552.  
  553.     // TITLE
  554.  
  555.         Label title=new Label("Collate Demo", Label.CENTER);
  556.         title.setFont(Utility.titleFont);
  557.  
  558.         Label demo=new Label(creditString, Label.CENTER);
  559.         demo.setFont(Utility.creditFont);
  560.  
  561.         Panel titlePanel = new Panel();
  562.         titlePanel.add(title);
  563.         titlePanel.add(demo);
  564.         Utility.fixGrid(titlePanel,1);
  565.         add("North", titlePanel);
  566.  
  567.     // CHECKBOXES
  568.  
  569.         checkboxes= new CheckboxGroup();
  570.  
  571.         sortAscending = new Checkbox("Sort Ascending",checkboxes, false);
  572.     sortAscending.addItemListener(this);
  573.         sortAscending.setFont(Utility.choiceFont);
  574.         sortAscending.setSize(100, 20);
  575.  
  576.         sortDescending = new Checkbox("Sort Descending",checkboxes, false);
  577.     sortDescending.addItemListener(this);
  578.         sortDescending.setSize(100, 20);
  579.         sortDescending.setFont(Utility.choiceFont);
  580.  
  581.         noSort = new Checkbox("Not Sorted",checkboxes, true);
  582.         noSort.setFont(Utility.choiceFont);
  583.         noSort.setSize(100, 20);
  584.  
  585.         Panel buttonPanel = new Panel();
  586.         buttonPanel.setLayout(new GridLayout(3,1,0,0));
  587.         buttonPanel.add(sortAscending);
  588.         buttonPanel.add(sortDescending);
  589.         buttonPanel.add(noSort);
  590.  
  591.     // LOCALE
  592.         Locale myLocale = new Locale("","","");
  593.  
  594.         Label localeLabel = new Label("Locale:   ");
  595.         localeLabel.setFont(Utility.choiceFont);
  596.  
  597.         localeChoice = new Choice();
  598.     localeChoice.addItemListener(this);
  599.  
  600.         //Get all locales for debugging, but only get G7 locales for demos.
  601.         if (DEBUG == true)
  602.              locales = Collator.getAvailableLocales();
  603.         else locales = Utility.getG7Locales();
  604.  
  605.         Locale displayLocale = null;
  606.         displayLocale = Locale.getDefault();
  607.         int defaultLoc = 0;
  608.         for (int i = 0; i < locales.length; i++) {
  609.             if (locales[i].getCountry().length() > 0) {
  610.                 localeChoice.addItem
  611.                     (locales[i].getDisplayName());
  612.                 if (locales[i].equals(displayLocale)) {
  613.                     defaultLoc = i;
  614.                 }
  615.             }
  616.         }
  617.         localeChoice.setFont(Utility.choiceFont);
  618.  
  619.         //must be called after the array of locales has been initialized
  620.         loadCollationTables();
  621.         localeChoice.select(defaultLoc);
  622.  
  623.         Panel localePanel = new Panel();
  624.         localePanel.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
  625.         localePanel.add(localeChoice);
  626.         // localePanel.setSize(200, 20);
  627.  
  628.         Label decompLabel = new Label("Decomposition Mode:");
  629.         decompLabel.setFont(Utility.labelFont);
  630.         decompChoice = new Choice();
  631.     decompChoice.addItemListener(this);
  632.         decompChoice.addItem(no_decomposition);
  633.         decompChoice.addItem(canonical_decomposition);
  634.         decompChoice.addItem(full_decomposition);
  635.         decompChoice.select(canonical_decomposition);
  636.         decompChoice.setFont(Utility.choiceFont);
  637.  
  638.         Panel decompPanel = new Panel();
  639.         decompPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0,0));
  640.         decompPanel.add(decompChoice);
  641.  
  642.         Label strengthLabel = new Label("Strength:");
  643.         strengthLabel.setFont(Utility.labelFont);
  644.  
  645.         strengthChoice = new Choice();
  646.     strengthChoice.addItemListener(this);
  647.         strengthChoice.addItem(tertiary);
  648.         strengthChoice.addItem(secondary);
  649.         strengthChoice.addItem(primary);
  650.         strengthChoice.setFont(Utility.choiceFont);
  651.  
  652.         Panel strengthPanel = new Panel();
  653.         strengthPanel.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
  654.         strengthPanel.add(strengthChoice);
  655.  
  656.  
  657.         Panel topPanel = new Panel();
  658.         //topPanel.setLayout(new GridLayout(4,1,0,0));
  659.         topPanel.add(buttonPanel);
  660.         topPanel.add(new Label(" ")); // quick & dirty gap
  661.         topPanel.add(localeLabel);
  662.         topPanel.add(localePanel);
  663.         topPanel.add(decompLabel);
  664.         topPanel.add(decompPanel);
  665.         topPanel.add(strengthLabel);
  666.         topPanel.add(strengthPanel);
  667.         Utility.fixGrid(topPanel,1);
  668.  
  669.         // TEXT
  670.  
  671.     textentry.addKeyListener(this);
  672.         textentry.setFont(editFont);
  673.         textentry.setText("black-birds\nPat\np\u00E9ch\u00E9\np\u00EAche\n" +
  674.             "p\u00E9cher\np\u00EAcher\nTod\nT\u00F6ne\nTofu\nblackbirds\n" +
  675.             "Ton\nPAT\nblackbird\nblack-bird\npat\n");
  676.  
  677.         //RULE ENTRY AREA
  678.         Panel ruleEntryPanel = new Panel();
  679.  
  680.         Panel rulePanel = new Panel();
  681.  
  682.         if (theCollation instanceof RuleBasedCollator)
  683.         {
  684.             String ruleText = ((RuleBasedCollator)theCollation).getRules();
  685.             ruleEntry.setFont(ruleFont);
  686.             ruleEntry.setText(createUnicodeString(ruleText));
  687.         }
  688.  
  689.         ruleEntryPanel.add(new Label("Collator Rules", Label.LEFT));
  690.         ruleEntryPanel.add(ruleEntry);
  691.  
  692.         collateRulesButton = new Button("Set Rules");
  693.     collateRulesButton.addActionListener(this);
  694.         collationName = new TextField(10);
  695.         collationName.setText("custom-" + untitledIndex);
  696.  
  697.         ruleEntryPanel.add(collateRulesButton);
  698.         ruleEntryPanel.add(new Label("Collator Name", Label.LEFT));
  699.         ruleEntryPanel.add(collationName);
  700.         Utility.fixGrid(ruleEntryPanel,1);
  701.  
  702.  
  703.         // PUT ALL TOGETHER
  704.  
  705.         Panel centerPanel = new Panel();
  706.         centerPanel.add(textentry);
  707.         centerPanel.add(topPanel);
  708.         centerPanel.add(ruleEntryPanel);
  709.         errorMsg.setFont(Utility.labelFont);
  710.         centerPanel.add(errorMsg);
  711.         Utility.fixGrid(centerPanel,3);
  712.  
  713.         add("Center", centerPanel);
  714.  
  715.         Panel bottomPanel = new Panel();
  716.         bottomPanel.setLayout(new GridLayout(2,1,0,0));
  717.  
  718.         addWithFont (bottomPanel,
  719.                      new Label(copyrightString, Label.LEFT),
  720.                      Utility.creditFont);
  721.         addWithFont (bottomPanel,
  722.                      new Label(copyrightString2, Label.LEFT),
  723.                      Utility.creditFont);
  724.         Utility.fixGrid(bottomPanel,1);
  725.         add("South", bottomPanel);
  726.     }
  727.  
  728.  
  729.     //------------------------------------------------------------
  730.     // private
  731.     //------------------------------------------------------------
  732.     /**
  733.      * This function is called by handleSortAscend and handleSortDescend
  734.      * to seperate each line of the textArea into individual strings,
  735.      * and add them to the vector to be sorted.
  736.      */
  737.     private void InitializeListVector()
  738.     {
  739.         textList.removeAllElements();
  740.  
  741.         String composite = textentry.getText();
  742.         char compositeArray[] = composite.toCharArray();
  743.         for (int i = 0; i < compositeArray.length; i++)
  744.         {
  745.            compositeArray[i] = (char) (compositeArray[i] & 0xFF);
  746.         }
  747.         composite = new String(compositeArray);
  748.  
  749.         String substr;
  750.  
  751.         int startOffset = 0;
  752.         int endOffset = 0;
  753.         for (; endOffset < composite.length(); endOffset++)
  754.         {
  755.             char ch = composite.charAt(endOffset);
  756.             if (ch == '\n' || ch == '\r')
  757.             {
  758.                 if (endOffset > startOffset)
  759.                 {
  760.                     substr = composite.substring(startOffset, endOffset);
  761.                     textList.addElement(substr);
  762.                 }
  763.                 startOffset = endOffset + 1;
  764.             }
  765.         }
  766.  
  767.         if (startOffset < composite.length())
  768.         {
  769.             substr = composite.substring(startOffset, composite.length());
  770.             textList.addElement(substr);
  771.         }
  772.  
  773.     }
  774.  
  775.  
  776.     /**
  777.      * This function is called by handleSortAscend and handleSortDescend
  778.      * to reset the text area based on the sort results stored as a vector
  779.      * of substrings.
  780.      */
  781.     private void resetTextArea()
  782.     {
  783.         String composite = new String();
  784.  
  785.         int i = 0;
  786.         for (; i < textList.size() - 1; i++)
  787.         {
  788.             composite = composite.concat((String) textList.elementAt(i));
  789.             composite = composite.concat("\n");
  790.         }
  791.         //don't add the \n to the end
  792.            composite = composite.concat((String) textList.elementAt(i));
  793.  
  794.         textentry.setText(composite);
  795.         textList.removeAllElements();
  796.     }
  797.  
  798.  
  799.  
  800.     private void errorText(String s)
  801.     {
  802.         if (!s.equals(errorMsg.getText()))
  803.         {
  804.             errorMsg.setText(s);
  805.             errorMsg.setSize(300, 50);
  806.         }
  807.     }
  808.  
  809.     private static StringBuffer oneChar = new StringBuffer(7);
  810.     private String makeDisplayString(char ch) {
  811.         oneChar.setLength(0);
  812.         if (ch < 0x0020 ||
  813.             (ch > 0x007D && ch < 0x00A0) ||
  814.             ch > 0x00FF) {
  815.             String temp = Integer.toString((int)ch,16).toUpperCase();
  816.             oneChar.append(temp);
  817.             if (temp.length() < 4)
  818.                 oneChar.append(zeros.substring(0,4-temp.length()));
  819.         } else {
  820.             oneChar.append(ch);
  821.         }
  822.         return oneChar.toString();
  823.     }
  824.  
  825.      /**
  826.     Changes a string into a representation that can be pasted into a program.
  827.     Uses \ t, \ uxxxx, etc. to display characters outside of Latin1.
  828.     Others are themselves.
  829.     */
  830.     private String createUnicodeString(String source)
  831.     {
  832.     StringBuffer result = new StringBuffer(source.length());
  833.     int len = 0;
  834.     int i = 0;
  835.     while (i < source.length()) {
  836.         char ch = source.charAt(i);
  837.         switch(ch) {
  838.        case '\'':
  839.             int mytemp = i;
  840.             int n = 0;
  841.             result.append(ch);
  842.             ch = source.charAt(++i);
  843.             while((ch != '\'') && (i < source.length() -1))
  844.             {
  845.                 String inquote = makeDisplayString(ch);
  846.                 n++; i++;
  847.                 if (inquote.length() > 1) {
  848.                     result.append("\\u");
  849.                     result.append(inquote);
  850.                     len += 6;
  851.                 } else {
  852.                     result.append(inquote);
  853.                     len++;
  854.                 }
  855.                 ch = source.charAt(i);
  856.             }
  857.             if (n == 0) {
  858.                 result.append('\'');
  859.                 n++; i++;
  860.                 ch = source.charAt(i);
  861.             }
  862.             result.append(ch);
  863.             len += n;
  864.             break;
  865.         case ';': case '=':
  866.             if (len > 15)
  867.             {
  868.                 result.append('\n');
  869.                 len = 0;
  870.             }
  871.             result.append(' ');
  872.             result.append(ch);
  873.             len += 2;
  874.             break;
  875.         case ',':
  876.             result.append(' ');
  877.             result.append(ch);
  878.             len += 2;
  879.             break;
  880.         case '<': case '&':
  881.             result.append('\n');
  882.             result.append(ch);
  883.             result.append(' ');
  884.             len = 0;
  885.             len += 2;
  886.             break;
  887.  
  888.         case '\n':
  889.             break;
  890.         default:
  891.             String dspString = makeDisplayString(ch);
  892.             if (dspString.length() > 1) {
  893.                 result.append("\\u");
  894.                 result.append(dspString);
  895.                 len += 6;
  896.             } else {
  897.                 result.append(dspString);
  898.                 len++;
  899.             }
  900.             break;
  901.         }
  902.         i++;
  903.     }
  904.     return result.toString();
  905.     }
  906.  
  907.     private static final String zeros = "0000";
  908.  
  909.  
  910.     private String convertStringToRules(String source)
  911.     {
  912.     StringBuffer result = new StringBuffer(source.length());
  913.     for (int i = 0; i < source.length(); ++i) {
  914.         //hack around TextArea bug
  915.         char ch = (char) (source.charAt(i) & 0xFF);
  916.         switch(ch) {
  917.         case '\n':
  918.             break;
  919.         case '\'':
  920.         if ((i+6 < source.length()) && (source.charAt(i+2) == 'u')) {
  921.         String temp = source.substring(i+3,i+7);
  922.         if (temp.equals("005c")) {
  923.             //have to handle backslash differently since 
  924.             //it is a special character in Java
  925.             result.append("'\\u005c'");
  926.         } else
  927.             result.append((char)(Integer.parseInt(temp,16)));
  928.         i = i + 7;
  929.         }
  930.         else result.append(ch);
  931.             break;
  932.         case '\\':
  933.           if ( (i+5 < source.length()) && (source.charAt(i+1) == 'u') )
  934.           {
  935.             String temp = source.substring(i+2,i+6);
  936.             result.append((char)(Integer.parseInt(temp,16)));
  937.             i = i + 6;
  938.            }
  939.            else result.append(ch);
  940.  
  941.             break;
  942.         default:
  943.             result.append(ch);
  944.             break;
  945.         }
  946.     }
  947.     return result.toString();
  948.     }
  949.  
  950.     private static final String creditString
  951.         = "v1.1a7, Demo";
  952.     private static final String copyrightString
  953.         = "";
  954.     private static final String copyrightString2
  955.         = "";
  956.  
  957.     // HSYS : fix
  958.     private static int MAX_COLLATIONS = 12;
  959.     private int untitledIndex = 1;
  960.     private static final int FIELD_COLUMNS = 45;
  961.     private static final Font editFont = new Font("TimesRoman",Font.PLAIN,18);
  962.     private static final Font ruleFont = new Font("TimesRoman",Font.BOLD,14);
  963.  
  964.     private static final boolean DEBUG = false;
  965.  
  966.     private TextArea textentry = new TextArea(10, 10);
  967.     private TextArea ruleEntry = new TextArea(10, 20);
  968.     private Vector textList = new Vector(15, 10);
  969.  
  970.     private Choice localeChoice;
  971.  
  972.     private static final String no_decomposition = "None";
  973.     private static final String canonical_decomposition = "Canonical";
  974.     private static final String full_decomposition = "Full";
  975.     private Choice decompChoice;
  976.  
  977.     private static final String tertiary = "Tertiary - a vs. A";
  978.     private static final String secondary = "Secondary - a vs. \u00E0";
  979.     private static final String primary = "Primary - a vs. b";
  980.     private Choice strengthChoice;
  981.  
  982.     private Locale theLocale = null;
  983.     private Collator theCollation = null;
  984.  
  985.     private Locale[] locales;
  986.     private Collator[] collations;
  987.     private String[] ruleStrings;
  988.     private Label errorMsg = new Label("", Label.LEFT);
  989.  
  990.     CheckboxGroup checkboxes;
  991.     Checkbox sortAscending;
  992.     Checkbox sortDescending;
  993.     Checkbox noSort;
  994.  
  995.     Button collateRulesButton;
  996.     TextField collationName;
  997.  
  998.     private DemoApplet applet;
  999.  
  1000. }
  1001.